package com.am.cell;

import java.util.ArrayList;
import java.util.List;

import com.am.AMObject;
import com.am.config.Configuration;
import com.am.link.Axon;
import com.am.link.HippoCampus;
import com.am.words.ICharacter;

public class Cell extends AMObject implements ICell {

	private ICharacter value;
	private int crs; // current release state
	private int voltage;
	private int distributableVoltage;
	private List<Axon> axons;
	private List<HippoCampus> hippoCampuses;

	public Cell() {
		super(Configuration.CELL_INIT_RESISTANCE);
		this.crs = Configuration.CELL_CURRENT_RELEASE_DURATION;
		this.voltage = Configuration.CELL_INIT_VOLTAGE;
		this.distributableVoltage = Configuration.CELL_VOLTAGE_DISTRIBUTION;
		this.axons = new ArrayList<Axon>();
		this.hippoCampuses = new ArrayList<HippoCampus>();
	}

	@Override
	public void addAxonLink(Axon link) {
		if(link.getSource().equals(this) && !this.axons.contains(link)){
			this.axons.add(link);
		}
	}

	@Override
	public void addHippoCampusLink(HippoCampus link) {
		if(link.getSource().equals(this) && !this.hippoCampuses.contains(link)){
			this.hippoCampuses.add(link);
		}
	}

	@Override
	public boolean addVoltage(int voltage) {
		this.voltage += voltage;
		if (this.voltage >= Configuration.CELL_FIREABLE_VOLTAGE) {
			// fired, start a new CRS
			this.crs = Configuration.CELL_CURRENT_RELEASE_DURATION;
			resetVoltage();
			return true;
		} else {
			return false;
		}
	}

	@Override
	public List<Axon> getAxons() {
		return this.axons;
	}

	@Override
	public List<HippoCampus> getHippoCampuses() {
		return this.hippoCampuses;
	}

	@Override
	public ICharacter getValue() {
		return value;
	}

	@Override
	public boolean isLinkable() {
		if (this.crs > 0) {
			this.crs--;
			return true;
		} else {
			return false;
		}
	}

	@Override
	public void setValue(ICharacter value) {
		this.value = value;
	}

	@Override
	public void resetVoltage() {
		this.voltage = Configuration.CELL_INIT_VOLTAGE;
	}

	@Override
	public int getDistributableVoltage() {
		return this.distributableVoltage;
	}

	@Override
	public boolean equals(Object o) {
		// Not strictly necessary, but often a good optimization
		if (this == o)
			return true;
		if (!(o instanceof Cell))
			return false;
		Cell co = (Cell) o;
		return value.equals(co.getValue());
	}
	
	@Override
	public int hashCode(){
		return value.hashCode();
	}

	@Override
	public Axon getAxon(ICell des) {
		for(Axon axon : this.axons){
			if(axon.getDestination().equals(des)){
				return axon;
			}
		}
		return null;
	}

	@Override
	public HippoCampus getHippoCampus(ICell des) {
		for(HippoCampus hc : this.hippoCampuses){
			if(hc.getDestination().equals(des)){
				return hc;
			}
		}
		return null;
	}

	@Override
	public void reLinkable() {
		this.crs = Configuration.CELL_CURRENT_RELEASE_DURATION;
	}
}
